package de.hwrberlin.remo.algorithm.steps;

import de.hwrberlin.expertsystem.util.ModelEditingHelper;
import de.hwrberlin.remo.model.ElementState;
import de.hwrberlin.remo.model.KnowledgeBaseElement;
import de.hwrberlin.remo.model.LinksFromFacts;
import de.hwrberlin.remo.model.Rule;
import de.hwrberlin.remo.model.LinksFromRules;

/**
 * Algorithm step, which sets the state of an element.
 * 
 * @author Mario S��nger (IT 09)
 * @version 1.0
 *
 */
public class SetStateStep implements AlgorithmStep {

	private ModelEditingHelper helper;
	private KnowledgeBaseElement element;
	private ElementState oldState;
	private ElementState newState;
	
	public SetStateStep(ModelEditingHelper helper, 
			KnowledgeBaseElement element, ElementState newState) {
		
		this.helper      = helper;
		this.element     = element;
		this.oldState    = element.getState();
		this.newState    = newState;
	}
	
	@Override
	public void perform() {
		helper.setElementState(element, newState);
	}

	@Override
	public void revert() {
		helper.setElementState(element, oldState);
	}

	@Override
	public String getLabel() {
		return "Setting " + element.getName() + " to " + newState.getLiteral();
	}

	@Override
	public String getExplanation() {
		StringBuilder explanation = new StringBuilder();
		
		explanation.append("Setting " + element.getName());
		explanation.append(" to " + newState.getLiteral());
		
		if(element instanceof Rule) {
			Rule rule = (Rule) element;

			explanation.append(" because:\n");
			
			for(LinksFromRules linkfromrule : rule.getRelatedlinkedrules()) {
				KnowledgeBaseElement referencedElement = linkfromrule.getRule();

				explanation.append("+ ");
				explanation.append(referencedElement.getName());
				explanation.append(" is ");
				if (linkfromrule.getLinkstate() == ElementState.TRUE){
					if (referencedElement.getState() == ElementState.TRUE){
						explanation.append("inverted to FALSE");
					}
					else{
						explanation.append("inverted to TRUE");
					}
				}
				else{
					explanation.append(referencedElement.getState().getLiteral());
				}
				explanation.append("\n");
			}
			
			for(LinksFromFacts linkfromfact : rule.getRelatedlinkedfacts()) {
				KnowledgeBaseElement referencedElement = linkfromfact.getFact();

				explanation.append("+ ");
				explanation.append(referencedElement.getName());
				explanation.append(" is ");
				if (linkfromfact.getLinkstate() == ElementState.TRUE){
					if (referencedElement.getState() == ElementState.TRUE){
						explanation.append("inverted to FALSE");
					}
					else{
						explanation.append("inverted to TRUE");
					}
				}
				else{
					explanation.append(referencedElement.getState().getLiteral());
				}
				explanation.append("\n");
			}
			
		}
		
		return explanation.toString();
	}
}